﻿using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.ComponentModel;
using System.Reflection;

namespace SwaggerDoc.Api
{
    /// <summary>
    ///OperationFilterFilter
    /// </summary>
    public class OperationFilter : IOperationFilter
    {
        /// <summary>
        /// Apply
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="context"></param>
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            var apiDescription = context.ApiDescription;

            //判断接口遗弃状态，对接口进行标记调整
            operation.Deprecated |= apiDescription.IsDeprecated();

            if (operation.Parameters == null)
            {
                return;
            }

            //api-version 参数添加必填验证
            foreach (var parameter in operation.Parameters)
            {
                var description = apiDescription.ParameterDescriptions.First(p => p.Name == parameter.Name);

                if (parameter.Description == null)
                {
                    parameter.Description = description.ModelMetadata?.Description;
                }

                if (parameter.Schema.Default == null && description.DefaultValue != null)
                {
                    parameter.Schema.Default = new OpenApiString(description.DefaultValue.ToString());
                }

                parameter.Required |= description.IsRequired;
            }
        }
    }

    /// <summary>
    /// DocumentFilter
    /// </summary>
    public class DocumentFilter : IDocumentFilter
    {
        /// <summary>
        /// Apply
        /// </summary>
        /// <param name="swaggerDoc"></param>
        /// <param name="context"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
        {
        }
    }

    /// <summary>
    /// SchemaFilter
    /// </summary>
    public class SchemaFilter : ISchemaFilter
    {
        /// <summary>
        /// Apply
        /// </summary>
        /// <param name="schema"></param>
        /// <param name="context"></param>
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            if (!context.Type.IsEnum)
            {
                return;
            }

            schema.Enum.Clear();
            foreach (var name in Enum.GetNames(context.Type))
            {
                Enum e = (Enum)Enum.Parse(context.Type, name);

                schema.Enum.Add(new OpenApiString($"{e:D}={GetDescription(e)}"));
            }
        }

        /// <summary>
        /// GetDescription
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string GetDescription(Enum value)
        {
            FieldInfo field = value.GetType().GetField(value.ToString());

            var va = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;

            return va == null ? value.ToString() : va.Description;
        }
    }
}
